/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package processer;

import main.BotManager;
import utils.Debug;

/**
 *
 * @author daz
 */
public class TienlenPlayer extends Player {

    private static final int NUMBER_CARD_IN_HANDS = 13;
    private static final int TIME_FOR_THINK = 30;
    //--------------------------------------------------------------------------
    private int blockType;
    private int lastPlayerFightId;
    private int gameResultOrder;
    private int playerFightId;
    private int numberPlayersStart;
    private int cardMoveIndex;
    private int cardOnTablesIndex;
    private int skipTurnId;
    private int numberBackCards;
    private boolean isDrawClock;
    private boolean isBeginGame;
    private boolean isDrawResutl;
    private boolean isCardMove;
    private boolean isFinishRound;
    private boolean isLastBlock;
    //-----------------------------------------------------------------------
    private boolean[] skipArr;
    private boolean[] finishArr;
//    private boolean[] isPlayingArr;
    private int[] resultOrder;
    private int[] numberCardInHand;
    private int[] cardSendToServer;
    private int[] backCardIds;
    private int timeForThink;
    private long lastTime;
//    private int myViewId;
    private int gameTurn;
//    private boolean isViewer;
    private int numberCardRemains;
    private Card[] cardInHands;
    private boolean isFinishGame;
    private boolean isHave3Bich;

    public TienlenPlayer(RoBot parent, GameData gameData, BotManager manager) {
        super(parent, gameData, manager);
        initValue();
        initObject();
        if (gameData.cardInHandId != null) {
            setCardShare(gameData.cardInHandId);
        } else {
            initForView();
        }
    }

    private void initValue() {
        timeForThink = TIME_FOR_THINK;
        lastTime = 0;
        blockType = -1;
        lastPlayerFightId = -1;
        playerFightId = -1;
        isDrawClock = true;
        isBeginGame = true;
        gameResultOrder = -1;
        maxPlayer = gameData.getMaxPlayer();
        myViewId = gameData.getMyViewId();
        playerId = gameData.getPlayerId();
        gameTurn = gameData.getFirstTurn();
        isViewer = (myViewId < maxPlayer ? false : true);
        if (isViewer) {
            playerId = 0;
        }
        gameTurn = gameData.getFirstTurn();
        numberPlayers = gameData.getNumberPlayers();
        gameData.setGameDisplay(this);
    }

    private void initObject() {
        skipArr = new boolean[maxPlayer];
//        isPlayingArr = gameData.getIsPlay();
        finishArr = new boolean[maxPlayer];
        resultOrder = new int[maxPlayer];
    }

    public void sortCardTienlen(int[] dataArr) {
        for (int i = 0, l = dataArr.length; i < l - 1; i++) {
            for (int j = i; j < l; j++) {
                if ((dataArr[i] % 13 + 11) % 13 > (dataArr[j] % 13 + 11) % 13) {
                    int tg = dataArr[i];
                    dataArr[i] = dataArr[j];
                    dataArr[j] = tg;
                } else if (dataArr[i] % 13 == dataArr[j] % 13) {
                    if (dataArr[i] / 13 > dataArr[j] / 13) {
                        int tg = dataArr[i];
                        dataArr[i] = dataArr[j];
                        dataArr[j] = tg;
                    }
                }
            }
        }

    }

    private void setCardShare(int[] cardIds) {
        numberCardRemains = NUMBER_CARD_IN_HANDS;
        numberCardInHand = new int[maxPlayer];
        cardInHands = new Card[numberCardRemains];
        if (Debug.isTest) {
            cardIds[0] = 4;
            cardIds[1] = 26;
        }
        isHave3Bich = false;
        sortCardTienlen(cardIds);
        for (int i = 0; i < numberCardRemains; i++) {
            int id = cardIds[i];
            if (id == 2) {
                isHave3Bich = true;
            }
            cardInHands[i] = new Card(id);
            Debug.d(i + ":" + cardInHands[i].rankName() + " " + cardInHands[i].getSuit());
            if (i < maxPlayer) {
                numberCardInHand[i] = NUMBER_CARD_IN_HANDS;
            }
        }
        numberPlayersStart = numberPlayers;
    }

    private void initForView() {
    }

    @Override
    void doFightCard() {
        if (isFinishGame) {
            if (!isViewer) {
                parent.request.finishTienlen();
            }
            return;
        }
        if (gameTurn == playerId && !isViewer) {
            chooseFightCard();
        }
    }

    private void finishRound() {

        for (int i = 0; i < skipArr.length; i++) {
            skipArr[i] = false;
        }
        playerFightId = -1;
        numberBackCards = 0;
        cardOnTablesIndex = 0;
    }

    private void nextGameTurn() {
        isBeginGame = false;
        isFinishRound = false;
        int preGameTurn = gameTurn;
        isLastBlock = false;
        for (int i = gameTurn + 1; i <= gameTurn + maxPlayer; i++) {
            int j = i % maxPlayer;
            if (!finishArr[j] && gameData.isPlays[j] && !skipArr[j]) {
                gameTurn = j;
                if (gameTurn == preGameTurn) {
                    isLastBlock = true;
                }
                break;
            }
        }
        // Debug.d("id vua danh :" + playerFightId);
        timeForThink = TIME_FOR_THINK;
        isDrawClock = true;
        if (gameTurn == preGameTurn) {
            finishRound();
            if (!isLastBlock) {
                //    Debug.d("ko ai du suc chan duoc:" + isLastBlock);
                nextGameTurn();
            }
            return;
        }
        //het 1 vong
        if (gameTurn == playerFightId) {
            //   Debug.d("finish round");
            isFinishRound = true;
            finishRound();
        }

        if (numberBackCards == 0 && !isFinishRound) {
            blockType = -1;
        }

    }

    private int blockZeroCard() {
        int[] cardFight = new int[numberCardRemains];
        int count = 0;
        if (!isHave3Bich) {
//            for (int i = 0; i < numberCardRemains; i++) {
//                int cardStart = cardInHands[i].rank();
//                if (numberCardRemains > 2) {
//                    if (cardInHands[i + 1].rank() == cardStart) {
//                        cardFight[count] = cardInHands[i].getCardId();
//                        cardFight[count + 1] = cardInHands[i + 1].getCardId();
//                        Debug.d(count + ":" + cardInHands[i].getCardId());
//                        Debug.d(count + ":" + cardInHands[i + 2].getCardId());
//                        count += 2;
//                        if (numberCardRemains > 3) {
//                            if (cardInHands[i + 2].rank() == cardStart) {
//                                cardFight[count] = cardInHands[i + 2].getCardId();
//                                Debug.d(count + ":" + cardInHands[i + 2].getCardId());
//                                count++;
//                            }
//
//                        }
//                        if (numberCardRemains > 4) {
//                            if (cardInHands[i + 3].rank() == cardStart) {
//                                cardFight[count] = cardInHands[i + 3].getCardId();
//                                Debug.d(count + ":" + cardInHands[i + 2].getCardId());
//                                count++;
//                            }
//                        }
//                    }
//                    if (count >= 2) {
//                        break;
//                    } else {
//                        count = 0;
//                    }
//                }
//            }
        } else {
            isHave3Bich = false;
            for (int i = 0; i < numberCardRemains; i++) {
                if (cardInHands[i].getCardId() == 2) {
                    cardInHands[i].setState(Card.STATE_HEIGHT);
                    return 1;
                }
            }
        }

        if (count == 0) {
            cardInHands[0].setState(Card.STATE_HEIGHT);
            return 1;
        } else {
            for (int i = 0; i < count; i++) {
                for (int j = i + 1; j < numberCardRemains; j++) {
                    if (cardInHands[j].getCardId() == cardFight[i]) {
                        cardInHands[j].setState(Card.STATE_HEIGHT);
                        j = numberCardRemains;
                    }
                }
            }
            return count;
        }
    }

    private int blockTwoCard() {
        Debug.d("block 2 card");
        for (int i = 0; i < numberCardRemains; i++) {
            if (cardInHands[i].rank() > (backCardIds[0] - 2 + 13) % 13) {
                for (int j = i + 1; j < numberCardRemains; j++) {
                    if (cardInHands[j].rank() == cardInHands[i].rank()) {
                        Debug.d("card 1:" + cardInHands[i].getCardId());
                        Debug.d("card 2:" + cardInHands[j].getCardId());
                        cardInHands[i].setState(Card.STATE_HEIGHT);
                        cardInHands[j].setState(Card.STATE_HEIGHT);
                        return 2;
                    }
                }
            }
        }
        return 0;
    }

    private int blockOneCard() {
        for (int i = 0; i < numberCardRemains; i++) {
            if ((cardInHands[i].getCardId() - 2 + 13) % 13 > (backCardIds[0] - 2 + 13) % 13) {
                cardInHands[i].setState(Card.STATE_HEIGHT);
                return 1;
            }
        }
        return 0;
    }

    private void chooseFightCard() {
        //chon quan danh
        int numberCardChoose = 0;
        switch (numberBackCards) {
            case 0:
                numberCardChoose = blockZeroCard();
                break;
            case 1:
                numberCardChoose = blockOneCard();
                break;
            case 2:
                numberCardChoose = blockTwoCard();
                break;
            case 3:
                break;
        }
        if (numberCardChoose == 0) {
            parent.request.skipTurnTienlen(playerId);
            if (numberBackCards > 0) {
                skipArr[playerId] = true;
            }
            return;
        }
        //gui bai len server 
        cardSendToServer = new int[numberCardChoose];
        int cardSendIndex = 0;
        for (int i = 0; i < numberCardRemains; i++) {
            if (cardInHands[i].getState() == Card.STATE_HEIGHT) {
                Card card = cardInHands[i];
                cardSendToServer[cardSendIndex] = card.getCardId();
                cardSendIndex++;
            }
        }
        sortCardTienlen(cardSendToServer);

        parent.request.fightCardTienlen(playerId, playerFightId, blockType, cardSendToServer);
        playerFightId = playerId;
        //bo bai ra
        for (int i = 0; i < numberCardRemains; i++) {
            if (cardInHands[i].getState() == Card.STATE_HEIGHT) {
                for (int j = i; j < numberCardRemains - 1; j++) {
                    cardInHands[j] = cardInHands[j + 1];
                }
                cardInHands[numberCardRemains - 1] = null;
                numberCardRemains--;
                i -= 1;
            }
        }
        nextGameTurn();
        isBeginGame = false;
        //kiem tra het bai
        if (playerFightId != -1) {
            numberCardInHand[playerFightId] -= numberBackCards;
        }
        if (!isViewer) {
            if (numberCardRemains == 0 && !finishArr[playerId]) {
                // het bai
                gameResultOrder++;
                resultOrder[playerId] = gameResultOrder;
                finishArr[playerId] = true;
                isDrawResutl = true;
                if (numberPlayers > 2) {
                    parent.request.tienlenFn2(resultOrder[playerId], numberPlayersStart, playerId);
                } else {
                    parent.request.tienlenFn3(resultOrder[playerId], numberPlayersStart, playerId);
                }
            }
        }
    }

    private int checkCardFinish(int[] card, int sumCard, StringBuffer buffer, StringBuffer chatBuffer) {
        int sumCheck = 0;
        boolean[] b = new boolean[sumCard];
        for (int i = 0; i < sumCard; i++) {
            b[i] = true;
        }
        // Sort Card
        for (int i = 0; i < sumCard - 1; i++) {
            for (int j = i + 1; j < sumCard; j++) {
                if (card[i] % 13 > card[j] % 13) {
                    int tg = card[i];
                    card[i] = card[j];
                    card[j] = tg;
                } else {
                    if (card[i] % 13 == card[j] % 13) {
                        if (card[i] / 13 > card[j] / 13) {
                            int tg = card[i];
                            card[i] = card[j];
                            card[j] = tg;
                        }
                    }
                }
            }
        }
        for (int i = 0; i < sumCard - 4; i++) {
            if (card[i] % 13 == card[i + 1] % 13 && card[i] % 13 == card[i + 2] % 13 && card[i] % 13 == card[i + 3] % 13) {
                chatBuffer.append("Thúi tứ quý");
                buffer.append(1);
                sumCheck = 1;
                b[i] = false;
                b[i + 1] = false;
                b[i + 2] = false;
                b[i + 3] = false;
                break;
            }
        }
        for (int i = 0; i < sumCard - 6; i++) {
            if (card[i] % 13 == card[i + 1] % 13 && card[i] % 13 > 1 && card[i] % 13 < 12) {
                boolean ok1 = false, ok2 = false;
                for (int j = i + 2; j < sumCard - 1; j++) {
//                    if (card[j] / 13 == card[j + 1] / 13 && card[j] / 13 == card[i] / 13) {
                    if (card[j] % 13 == card[j + 1] % 13) {
                        if (card[i] % 13 + 1 == card[j] % 13) {
                            ok1 = true;
                        }
                        if (card[i] % 13 + 2 == card[j] % 13) {
                            ok2 = true;
                        }
                    }
//                    }
                }
                if (ok1 && ok2) {
                    if (sumCheck == 0) {
                        chatBuffer.append("Thúi 3 đôi thông");
                    } else {
                        chatBuffer.append(", 3 đôi thông");
                    }
                    sumCheck += 2;
                    buffer.append(2);
                    break;
                }
            }
        }
        for (int i = 0; i < sumCard; i++) {
            if (card[i] == 1) {
                if (sumCheck == 0) {
                    chatBuffer.append("Thúi 2 bích");
                } else {
                    chatBuffer.append(", 2 bích");
                }
                sumCheck += 4;
                buffer.append(4);
            }
            if (card[i] == 14) {
                if (sumCheck == 0) {
                    chatBuffer.append("Thúi 2 tép");
                } else {
                    chatBuffer.append(", 2 tép");
                }
                sumCheck += 8;
                buffer.append(8);
            }
            if (card[i] == 27) {
                if (sumCheck == 0) {
                    chatBuffer.append("Thúi 2 rô");
                } else {
                    chatBuffer.append(", 2 rô");
                }
                sumCheck += 16;
                buffer.append(16);

            }
            if (card[i] == 40) {
                if (sumCheck == 0) {
                    chatBuffer.append("Thúi 2 cơ");
                } else {
                    chatBuffer.append(", 2 cơ");
                }
                sumCheck += 32;
                buffer.append(32);

            }
        }

        return sumCheck;
    }

    private void checkFinish() {
        int[] card = new int[NUMBER_CARD_IN_HANDS];
        for (int i = 0; i < numberCardRemains; i++) {
            card[i] = cardInHands[i].getCardId();
        }
        StringBuffer buffer = new StringBuffer();
        StringBuffer chatBuffer = new StringBuffer();

        buffer.append("TH|").append(playerId).append("|").append(playerId).append("|");
        int sumCheck = checkCardFinish(card, numberCardRemains, buffer, chatBuffer);
        if (sumCheck > 0) {
            parent.request.chat(chatBuffer.toString());
            parent.request.request(buffer.toString());
        }
    }

    private void processDBMessage(String[] part) {
        //DB2|id danh|lastActice|chatquan|ID các quân bài
        int db2Id = Integer.parseInt(part[1]);
        if (isViewer) {
            gameTurn = db2Id;
        }
        if (db2Id != playerId || isViewer) {
            playerFightId = db2Id;
            lastPlayerFightId = Integer.parseInt(part[2]);
            blockType = Integer.parseInt(part[3]);
            int numberFightCard = part.length - 4;
            backCardIds = new int[numberFightCard];
            numberBackCards = numberFightCard;
            for (int i = 0; i < numberFightCard; i++) {
                int cardId = Integer.parseInt(part[i + 4]);
                backCardIds[i] = cardId;
            }
            nextGameTurn();
            if (playerFightId != -1) {
                numberCardInHand[playerFightId] -= numberBackCards;
            }
        }
    }

    private int getPosId(int id) {
        return (id - playerId + maxPlayer) % maxPlayer;
    }

    @Override
    public void processMesage(String[] part) {
        Debug.d("tien len process");
        super.processMesage(part);
        if (part[0].equals("DB2")) {
            processDBMessage(part);
            return;
        }

        if (part[0].equals("SE")) {
            gameData.setNumberPlayerInTable(part);
            parent.changeProcesser(RoBot.TABLE_CHOOSER);
            return;
        }
        if (part[0].equals("RO")) {
            gameData.setRoArrData(part);
            if (numberPlayers == 1
                    || numberPlayers - gameResultOrder - 2 == 0) {
                isFinishGame = true;
                isDrawResutl = true;
                parent.changeProcesser(RoBot.WAITING);
                parent.request.changeReadyState(0);
            }
            if (!gameData.isPlays[gameTurn] && !isFinishGame) {
                nextGameTurn();
            }
            return;
        }
        if (part[0].equals("BL")) {
            if (!isFinishGame) {
                skipTurnId = Integer.parseInt(part[1]);
                if (numberBackCards > 0) {
                    skipArr[skipTurnId] = true;
                }
                int posId = (skipTurnId - playerId + maxPlayer) % maxPlayer;
                nextGameTurn();
            }
            return;
        }
        if (part[0].equals("FN2")) {
            int idFinish = Integer.parseInt(part[3]);
            if ((idFinish != playerId) || isViewer) {
                resultOrder[idFinish] = Integer.parseInt(part[1]);
                finishArr[idFinish] = true;
                gameResultOrder = resultOrder[idFinish];
            }
            if (numberPlayers - gameResultOrder - 2 == 0) {
                isDrawResutl = true;
                int lastId = 0;
                for (int i = 0; i < numberPlayers; i++) {
                    if (!finishArr[i] && gameData.isPlays[i]) {
                        finishArr[i] = true;
                        resultOrder[i] = gameResultOrder + 1;
                        lastId = i;
                        break;
                    }
                }
                isFinishGame = true;
                if (playerId == lastId) {
                    checkFinish();
                }

            }
            return;
        }

        if (part[0].equals("MO")) {
            gameData.setMoArrData(part);
            return;
        }
        if (part[0].equals("RE")) {
            gameData.setReArrData(part);
            return;
        }
        if (part[0].equals("CM")) {
            int money = Integer.parseInt(part[2]);
            int id = Integer.parseInt(part[1]);
            int posId = (id - playerId + maxPlayer) % maxPlayer;
            gameData.changeMoney(id, money);
            return;
        }

        if (part[0].equals("INFO")) {
            gameData.setInfoData(part);
            return;
        }
        if (part[0].equals("CT")) {
            parent.request.changeReadyState(0);
            parent.changeProcesser(RoBot.WAITING);
            return;
        }
    }
}
